﻿namespace EasyToolkit.BindingTemplates.Definitions.Binding
{
    using System.Collections.Generic;
    using System.Linq;

    public class BindingDefinitionDescription
    {
        public string Name
        { get; set; }

        public bool IsConst
        { get; set; }

        public bool IsReadOnly
        { get; set; }

        public string BindingExpression
        { get; set; }

        public string Description
        { get; set; }

        public List<string> Options
        { get; set; }

        #region .ctors and factories
        public BindingDefinitionDescription()
        {}

        public BindingDefinitionDescription(string bindingExpression, bool isConst, List<string> options)
        {
            BindingExpression = bindingExpression;
            IsConst = isConst;
            if (options != null)
            {
                IsReadOnly = options.Contains("R");
                options.Remove("R");

                if (options.Count > 0)
                {
                    string nameOption = null;
                    string descriptionOption = null;
                    foreach (string option in options)
                    {
                        if (option.StartsWith("D="))
                        {
                            descriptionOption = option;
                            Description = descriptionOption.Substring(2);
                        }
                        if (option.StartsWith("N="))
                        {
                            nameOption = option;
                            Name = nameOption.Substring(2);
                        }
                    }

                    if (nameOption != null)
                        options.Remove(nameOption);
                    if (descriptionOption != null)
                        options.Remove(descriptionOption);

                    if (options.Count > 0)
                        Options = options;
                }
            }
        }

        static public BindingDefinitionDescription CreateBindingDescription(string toAnalyze, string trimmedToAnalyze)
        {
            BindingDefinitionDescription ret = null;
            if (!string.IsNullOrEmpty(trimmedToAnalyze))
            {
                bool isConstante = false;
                List<string> options = null;

                if (! trimmedToAnalyze.StartsWith("{"))
                    isConstante = true;
                else
                {
                    if (!trimmedToAnalyze.EndsWith("}"))
                        throw new BindingTemplateException(string.Format("Cannot create BindingDefinition from '{0}': cannot find the closing '}'", toAnalyze));

                    trimmedToAnalyze = trimmedToAnalyze.Substring(1, trimmedToAnalyze.Length - 2);

                    int compoStart = trimmedToAnalyze.IndexOf('{');
                    string toAnalyzeOptions = compoStart == -1 ? trimmedToAnalyze : trimmedToAnalyze.Substring(0, compoStart);
                    string[] parts = toAnalyzeOptions.Split(':');
                    if (parts.Count() > 2)
                        throw new BindingTemplateException(string.Format("Cannot create BindingDefinition from '{0}': options not properly set. Syntax is: [opt1, opt2...]:{...}", toAnalyze));

                    if (parts.Count() == 2)
                    {
                        string optionsString = parts[0];
                        string[] optionsArray = optionsString.Split(',');
                        options = optionsArray.Where(p => !string.IsNullOrEmpty(p))
                                              .Select(p => p.Trim())
                                              .ToList();
                        trimmedToAnalyze = parts[1];
                    }
                }
                ret = new BindingDefinitionDescription(isConstante ? toAnalyze : trimmedToAnalyze, isConstante, options);
            }
            return ret;
        }
        #endregion
    }
}
